/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.openide.explorer.propertysheet; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.lang.reflect.*; import javax.swing.*; import javax.swing.border.*; import org.openide.awt.*; import org.openide.explorer.propertysheet.editors.NodePropertyEditor; import org.openide.nodes.PropertySupport; import org.openide.nodes.Node; import org.openide.util.Utilities; /** * This class encapsulates working with indexed properties. */ class IndexedPropertyEditor extends Object implements NodePropertyEditor { static java.util.ResourceBundle bundle = org.openide.util.NbBundle.getBundle ( IndexedPropertyEditor.class); // ----------------------------------------------------------------------------- // Private variables private PropertyDetails details; /** The PropertyEditor of the array items type */ private PropertyEditor delegate; /** If true, indexed acces should be used, * if false, setter/getter for whole array should be used */ private boolean isIndexedValue; private Class itemType; private Object[] array; private Node[] nodes; private PropertyChangeSupport propertySupport = new PropertyChangeSupport (this); // ----------------------------------------------------------------------------- // init public IndexedPropertyEditor(PropertyDetails details) { this.details = details; delegate = details.getIndexedPropertyEditor (); itemType = details.getIndexedValueType (); updateArray (); } // ----------------------------------------------------------------------------- // NodePropertyEditor implementation public void attach (Node[] nodes) { this.nodes = nodes; } // ----------------------------------------------------------------------------- // PropertyEditor implementation public void setValue(Object value) { if (!value.getClass ().isArray ()) throw new IllegalArgumentException (); array = Utilities.toObjectArray (value); } public Object getValue() { return array; } public boolean isPaintable() { return false; } public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { } public String getJavaInitializationString(int index) { if (array[index] == null) return "null"; // NOI18N try { delegate.setValue (array [index]); return delegate.getJavaInitializationString (); } catch (NullPointerException e) { return "null"; // NOI18N } } public String getJavaInitializationString() { if (array == null) return ""; // NOI18N StringBuffer buf = new StringBuffer ("new "); // NOI18N buf.append (itemType.getName ()); // empty array if (array.length == 0) { buf.append ("[0]"); // NOI18N } else // non-empty array { buf.append ("[] {\n\t"); // NOI18N for (int i = 0; i < array.length; i++) { try { delegate.setValue (array[i]); buf.append (delegate.getJavaInitializationString ()); } catch (NullPointerException e) { buf.append ("null"); // NOI18N } if (i != array.length - 1) buf.append (",\n\t"); // NOI18N else buf.append ("\n"); // NOI18N } buf.append ("}"); // NOI18N } return buf.toString (); } public String getAsText() { if (array == null) return "null"; // NOI18N StringBuffer buf = new StringBuffer ("["); // NOI18N for (int i = 0; i < array.length; i++) { try { delegate.setValue (array[i]); buf.append (delegate.getJavaInitializationString ()); } catch (NullPointerException e) { buf.append ("null"); // NOI18N } if (i != array.length - 1) buf.append (", "); // NOI18N } buf.append ("]"); // NOI18N return buf.toString (); } public void setAsText(String text) throws java.lang.IllegalArgumentException { } public String[] getTags() { return null; } public Component getCustomEditor() { if (delegate.supportsCustomEditor ()) return new CustomIndexedPropertyPanel (); else return new IndexedPropertyPanel (); } public boolean supportsCustomEditor() { return true; } public void addPropertyChangeListener(PropertyChangeListener listener) { propertySupport.addPropertyChangeListener (listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propertySupport.removePropertyChangeListener (listener); } // other methods ........................................................................ void firePropertyChange () { propertySupport.firePropertyChange ("value", null, null); // NOI18N } /** * Returns if property has indexed setter. */ public boolean isIndexed () { return details.canWrite (PropertyDetails.INDEXED); } /** * Sets value of array through nonindexed setter. */ void updateArray () { array = null; try { if (details.canRead (PropertyDetails.NORMAL)) setValue (details.getPropertyValue ()); } catch (Exception e) { } return; } /** * Sets a new value of item on index specified. */ void setItem (Object o, int index) { try { if (details.canWrite (PropertyDetails.INDEXED)) { details.setPropertyValue (o, index); IndexedPropertyEditor.this.firePropertyChange (); updateArray (); } else if (details.canWrite (PropertyDetails.NORMAL) && details.canRead (PropertyDetails.NORMAL) ) { array [index] = o; Object[] a = (Object [])Array.newInstance ( Utilities.getObjectType (details.getIndexedValueType ()), array.length ); System.arraycopy (array, 0, a, 0, array.length); array = a; Class itemClass = details.getIndexedValueType (); if (!itemClass.isPrimitive ()) details.setPropertyValue (array); else details.setPropertyValue (Utilities.toPrimitiveArray (array)); IndexedPropertyEditor.this.firePropertyChange (); updateArray (); } } catch (Exception ee) { } } // innerclasses ........................................................................ /** * Abstract panel showing value of one item of array. */ abstract class AbstractIndexedPropertyPanel extends JPanel { /** Input component. */ private Component inputComponent; Object value; int index; SpinButton spinButton; JTextField tfSize, tfIndex; static final long serialVersionUID =4649444616108622547L; /** */ protected void init () { setLayout (new BorderLayout (3, 3)); setBorder (new EmptyBorder (6, 6, 0, 6)); JPanel p = new JPanel (new BorderLayout ()); p.setBorder (new CompoundBorder ( new EtchedBorder (), new EmptyBorder (2, 2, 2, 2) )); JPanel pp = new JPanel (); pp.setLayout (new GridLayout (2, 1, 3, 3)); JPanel p1 = new JPanel (); p1.setLayout (new BorderLayout (3, 3)); p1.add ("West", new JLabel (bundle.getString ("CTL_Index"))); tfIndex = new JTextField ("0", 4); // NOI18N tfIndex.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent e) { JTextField tField = (JTextField)e.getSource (); String s = tField.getText (); int i = 0; try { i = Integer.parseInt (s); } catch (NumberFormatException ee) { tField.setText ("0"); // NOI18N return; } setInput (i); spinButton.setValue (i); } }); p1.add (tfIndex, "Center"); // NOI18N pp.add (p1); p1 = new JPanel (); p1.setLayout (new BorderLayout (3, 3)); p1.add (new JLabel ("Size :"), "West"); // NOI18N tfSize = new JTextField ("", 4); // NOI18N tfSize.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent e) { JTextField tField = (JTextField)e.getSource (); String s = tField.getText (); int i = 0; try { i = Integer.parseInt (s); } catch (NumberFormatException ee) { tField.setText ("0"); // NOI18N return; } Object[] a = (Object [])Array.newInstance ( Utilities.getObjectType (details.getIndexedValueType ()), i ); if (array != null) System.arraycopy (array, 0, a, 0, Math.min (array.length, a.length)); array = a; Class itemClass = details.getIndexedValueType (); if (!itemClass.isPrimitive ()) details.setPropertyValue (array); else details.setPropertyValue (Utilities.toPrimitiveArray (array)); IndexedPropertyEditor.this.firePropertyChange (); updateArray (); spinButton.setMaximum (array.length - 1); spinButton.setValue (index); } }); if (!details.canWrite (PropertyDetails.NORMAL)) tfSize.setEnabled (false); if (array == null) tfSize.setText (bundle.getString ("CTL_Unknown")); else tfSize.setText ("" + array.length); // NOI18N p1.add (tfSize, "Center"); // NOI18N pp.add (p1); p.add (pp, "Center"); // NOI18N spinButton = new SpinButton (); // spinButton.setBoundsIgnored (true); spinButton.setMinimum (0); if (array != null) spinButton.setMaximum (array.length - 1); else spinButton.setMaximum (Integer.MAX_VALUE); spinButton.addSpinButtonListener (new SpinButtonAdapter () { public void moveUp () { setInput (++index); tfIndex.setText ("" + index); // NOI18N } public void moveDown () { setInput (--index); tfIndex.setText ("" + index); // NOI18N } }); p.add (spinButton, "East"); // NOI18N add (p, "North"); // NOI18N setInput (0); } /** * Returns component displaying value of one item of array. */ abstract Component getInputComponent (Object value); /** * Notifies about removing of InputComponent. */ void inputComponentRemoved () { } /** * Sete index of array. */ void setInput (int i) { index = i; value = null; boolean ok = false; if ((array != null) && (array.length > i)) { value = array [i]; ok = true; } else try { if (details.canRead (PropertyDetails.INDEXED)) { value = details.getPropertyValue (i); ok = true; } } catch (Exception e) { } if (ok) { Component c = getInputComponent (value); if (c != inputComponent) { if (inputComponent != null) remove (inputComponent); add ("Center", inputComponent = c); // NOI18N } else inputComponent.invalidate (); validate (); } else { inputComponentRemoved (); JPanel p1 = new JPanel (new FlowLayout (FlowLayout.CENTER)); if (inputComponent != null) remove (inputComponent); p1.add (new JLabel (bundle.getString ("CTL_NoItem"))); add ("Center", inputComponent = p1); // NOI18N validate (); } } } /** * Abstract panel showing value of one item of array as Custom ProeprtyEditor component. */ class CustomIndexedPropertyPanel extends AbstractIndexedPropertyPanel { PropertyChangeListener myListener; boolean listenerOn = false; Component customizer; PropertyEditor editor; static final long serialVersionUID =-711591659589018688L; CustomIndexedPropertyPanel () { // I'm listening not only on variable changing but on changes // of JComponent properties too. myListener = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent e) { Object o = editor.getValue (); setItem (o, index); } }; editor = details.getNewIndexedPropertyEditor (); init (); } void inputComponentRemoved () { if ((customizer != null) && (listenerOn)) editor.removePropertyChangeListener (myListener); } Component getInputComponent (Object value) { /* if (customizer != null) { if (listenerOn) editor.removePropertyChangeListener (myListener); System.out.println ("getInputComponent " + value); editor.setValue (value); editor.addPropertyChangeListener (myListener); listenerOn = true; return (Component)customizer; }*/ try { delegate.setValue (value); } catch (NullPointerException e) { } if (listenerOn) editor.removePropertyChangeListener (myListener); try { editor.setValue (value); } catch (NullPointerException e) { } customizer = editor.getCustomEditor (); editor.addPropertyChangeListener (myListener); listenerOn = true; return customizer; } public void removeNotify () { if (listenerOn) editor.removePropertyChangeListener (myListener); listenerOn = false; super.removeNotify (); } public void addNotify () { if (listenerOn) editor.removePropertyChangeListener (myListener); super.addNotify (); editor.addPropertyChangeListener (myListener); listenerOn = true; } } /** * Abstract panel showing value of one item of array as ProeprtyDisplayer component. */ class IndexedPropertyPanel extends AbstractIndexedPropertyPanel { PropertyDetails innerDetails; PropertyDisplayer displayer; static final long serialVersionUID =2643947136839393931L; IndexedPropertyPanel () { innerDetails = new PropertyDetails ( nodes, new PropertySupport.ReadWrite ( "", // NOI18N details.getIndexedValueType (), "", // NOI18N "" // NOI18N ) { public Object getValue () { return value; } public void setValue (Object val) throws IllegalArgumentException { value = val; setItem (val, index); } } ); displayer = new PropertyDisplayer (innerDetails); displayer.setSwitchAutomatically (false); init (); } Component getInputComponent (Object value) { displayer.setValue (new PropertyValue (innerDetails)); displayer.setInputState (true); return displayer; } } } /** Log * 2 Tuborg 1.1 08/13/98 Ian Formanek * 1 Tuborg 1.0 08/13/98 Ian Formanek * $ */